home *** CD-ROM | disk | FTP | other *** search
- ; vid -- Routines to synchronize switching between the two hardware screens
- ; in sync with the screen refresh, allowing smooth animation.
- ; mike morton, may 1986
-
- ; function vidwait (VAR block: vidinfo): longint; external;
- ; procedure vidstart (VAR block: vidinfo; period: integer); external;
- ; procedure getaltscreen; external;
-
- ; MDS ASSEMBLER VERSION
- ; Converted by David E. Smith for MacTutor.
- ;
- ;
- xdef vidwait
- xdef vidstart
- xdef getaltscreen
-
- Include QuickEqu.D ; MDS toolbox equates and traps
- Include SysEqu.D
- Include ToolEqu.D
- Include MacTraps.D
-
- MACRO .equ = equ| ; convert Lisa assembler stuff to MDS Mac
- MACRO _hidecurs = _HideCursor|
- MACRO _showcurs = _ShowCursor|
-
- ; definition of state information record. *** also defined on Pascal side. ***
-
- vblsize .equ vblphase+2 ; size of VBL block
-
- ivbl .equ 0 ; VBL task information
- ireq .equ ivbl+vblsize ; (integer) request: alt/default/stop/none
- iperiod .equ ireq+2 ; (integer) default period in ticks
- idelays .equ iperiod+2 ; (longint) number of times we've had to delay for a tick
-
- isize .equ idelays+4 ; size of “info” block
-
- viabase .equ $1D4 ;$1D4 VIA base address global (VIA)
- CurPage .equ $936 ;$936 alternate screen page status global (CurPageOption)
-
- ;
- ; request definitions: the high level code saves these for us to see.
- ; *** note: the code at “vbl” depends on these values. ***
- ;
- reqalt .equ 0 ; request switch to alternate screen
- reqdef .equ 1 ; request switch to default screen
- reqstop .equ 2 ; stop on default screen
- reqnone .equ 3 ; nothing requested
-
- ; ----------------------------------------------------------------------------
-
- ;
- ; function vidwait (block: ptr): longint; external;
- ; this routine is called when the next animation frame is ready to be shown
- ; and the main program has made a request to display that frame. it waits
- ; until the new frame is being shown, then returns. it also returns the
- ; approximate time it had to wait, in arbitrary units. this helps you find
- ; out how much slack you have between the time the frame is ready and the time
- ; it's actually used.
-
- vidwait:
- move.l (SP)+,A1 ; pop return
- move.l (SP)+,A0 ; pop block pointer
- moveq #-1,D0 ; will be 0 if we exit right away
-
- vidw2: addq.l #1,D0 ; bump spinning counter
- cmp.w #reqnone,ireq(A0) ; is nothing waiting to happen?
- bne.s vidw2 ; something pending: don't return yet
-
- move.l D0,(SP) ; return “time” waited
- jmp (A1) ; return
-
- ; ----------------------------------------------------------------------------
-
- ;
- ; procedure vidstart (block: ptr; period: integer); external;
- ;
-
- vidstart:
- move.l 6(SP),A0 ; point to VBL block (also info block)
- move.w 4(SP),D0 ; pick up desired period
-
- move.w #reqnone,ireq(A0) ; initialize request info to “none”
- move.w D0,iperiod(A0) ; save period
- clr.l idelays(A0) ; no delays seen yet
-
- move.w #vType,vblType(A0) ; set the type of queue element
- lea vbl,A1 ; point to VBL routine to call
- move.l A1,vblAddr(A0) ; save the address of the routine
- move.w D0,vblCount(A0) ; set time to wait for the first call
- clr.w vblPhase(A0) ; zero phase -- do I need to do this?
-
- _vInstall ; install the vertical retrace task
- tst.w D0 ; good status?
- bne.s death ; no: bag it
-
- @1 move.l (SP)+,A0 ; pop return
- addq.l #4+2,SP ; ding one long, one integer parameter
- jmp (A0) ; and return with the task queued
-
- ; ----------------------------------------------------------------------------
-
- ; this is our entry point from the vertical retrace manager.
- ; entered by: A0 points to VBL block; our state information follows this.
- ;
- ; - if no request has been made by the time we're called, the main program
- ; didn't have a frame to be drawn in time; in this case, we increment the
- ; “delays” counter and set the alarm to wake us up one tick from now.
- ; - if a request is there, we do it and set the alarm for one full period.
-
- vbl: move.w ireq(A0),D0 ; pick up the request
- move.w #reqnone,ireq(A0) ; cancel any pending request
- move.l viabase,A1 ; point to base of VIA stuff
-
- dbra D0,vbl1 ; skip if not zero
- bclr #6,$1E00(A1) ; alternate screen: clear the bit
- move.w iperiod(A0),vblCount(A0) ; ask for next wake-up at usual time
- rts ; exit
-
- vbl1: dbra D0,vbl2 ; wasn't zero; skip if not one
- bset #6,$1E00(A1) ; default screen: set the bit
- move.w iperiod(A0),vblCount(A0) ; ask for next wake-up at usual time
- rts ; ta da
-
- vbl2: dbra D0,vbl3 ; wasn't zero or one; skip if not two
- clr.w vblCount(A0) ; stop: we don't want to run again
- bset #6,$1E00(A1) ; default screen (make finder happy)
- rts ; home for the last time
-
- vbl3: dbra D0,death ; wasn't 0,1, or 2; die if not three
- move.w #1,vblCount(A0) ; no request: re-run in just one tick
- add.l #1,idelays(A0) ; keep stats on how often this happens
- rts ; and return
-
- death: DC.L $60FE ; execute an “ILLEGAL” instruction
-
- ; ----------------------------------------------------------------------------
-
- ; procedure getaltscreen; external;
- ; this should be the VERY first thing your application calls.
- ; - if the alternate video screen IS configured, we return and do nothing.
- ; - if the screen isn't there, we find out the application's name from the
- ; application parameters and relaunch ourselves, correctly configured.
-
-
- getaltscreen:
- tst.l CurPage ; pick up current screen configuration
- bpl.s relaunch ; negative means we got alt. screen
- rts ; all's well; return
-
- relaunch: ; here when we have to restart
- sub.l #32+4+2,SP ; room for apName, apRefNum, apParam
- move.l SP,A0 ; point to base of this stuff
- pea 4+2(A0) ; push arg1: VAR pointer to apName
- pea 4(A0) ; push arg2: VAR pointer to apRefNum
- pea 0(A0) ; push arg3: VAR pointer to apParam
- _GetAppParms ; fill in name, other junk; pop params
-
- ; Now apParam, apRefNum and (importantly) apName are in stack temps.
- lea 4+2(SP),A0 ; point to the name we just got
- move.l #-1,-(SP) ; -1 asks for alternate screen...
- move.l A0,-(SP) ; ...and point to name to launch
- move.l SP,A0 ; point to name ptr and flags with A0
- _launch ; launch ourselves, with alt screen
- bra.s death ; shouldn't reach here!
-
- end
-